package com.block.sms.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.common.constant.AppRspCodeConstant;
import com.block.common.constant.SmsConstant;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.util.CoderUtil;
import com.block.common.util.StringUtil;
import com.block.common.vo.ResponseVo;
import com.block.db.entity.*;
import com.block.db.mapper.SmsRecordInfoMapper;
import com.block.db.util.IdTypeEnum;
import com.block.db.util.SnowflakeUtil;
import com.block.sms.dto.QueryParamDTO;
import com.block.sms.dto.SmsParamDTO;
import com.block.sms.dto.SmsResultDTO;
import com.block.sms.service.ISmsConfigInfoService;
import com.block.sms.service.ISmsRecordService;
import com.block.sms.service.ISmsTemplateService;
import com.block.sms.service.factory.SmsSendFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.sql.Struct;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * 
 * @since 2021-02-16
 */
@Slf4j
@Service
public class SmsRecordServiceImpl extends ServiceImpl<SmsRecordInfoMapper, SmsRecordInfo> implements ISmsRecordService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    ISmsTemplateService smsTemplateService;
    @Autowired
    ISmsConfigInfoService smsConfigInfoService;
    @Autowired
    NotifyExceptionService notifyExceptionService;

    /**
     * 发送验证码类短信
     *
     * @param mobile
     * @param operationType
     * @return
     */
    @Override
    public ResponseVo sendSmsCode(String mobile, String operationType, String ip, ApplicationInfo applicationInfo, ChannelBaseInfo channelBaseInfo) {

        String code = StringUtil.getNumByLength(6);

        JSONArray paramArr = new JSONArray();
        paramArr.add(code);

        SmsParamDTO smsParamDTO = new SmsParamDTO();
        smsParamDTO.setMobie(mobile);
        smsParamDTO.setOtype(operationType);
        smsParamDTO.setReqIp(ip);
        smsParamDTO.setParamArray(paramArr);

        ResponseVo responseVo = this.sendSms(smsParamDTO, applicationInfo, channelBaseInfo);
        //redis记录操作类型和验证码
        if (!AppRspCodeConstant.SUCCESS.equals(responseVo.getRspCode())) {
            return responseVo;
        }
        String mobileStr = SecureUtil.md5(mobile).toLowerCase();
        stringRedisTemplate.opsForValue().set(SmsConstant.getCodeKey(operationType, mobileStr), code, SmsConstant.CODE_EXPRIES, TimeUnit.SECONDS);
        String codeCountKey = SmsConstant.getCodeCountKey(operationType, mobileStr);
        stringRedisTemplate.opsForValue().increment(codeCountKey);
        if (stringRedisTemplate.hasKey(codeCountKey)) {
            stringRedisTemplate.expire(codeCountKey, 1L, TimeUnit.DAYS);
        }
        return responseVo;
    }

    /**
     * 发送带参数的短信
     * @return
     */
    @Override
    public ResponseVo sendSms(SmsParamDTO smsParamDTO, ApplicationInfo applicationInfo, ChannelBaseInfo channelBaseInfo) {

        try {
            SmsTemplateInfo smsTemplate = smsTemplateService.getSmsTemplateByOtypeAndAppCode(smsParamDTO.getOtype(), applicationInfo.getAppCode());
            // todo redis 缓存优化
            SmsConfigInfo smsConfigInfo = smsConfigInfoService.getById(smsTemplate.getConfigId());

            // 发送短信 请求类

            String orderNo = SnowflakeUtil.getSnowflakeByDate(IdTypeEnum.COMMON,30);
            smsParamDTO.setOrderNo(orderNo);
            smsParamDTO.setPlatform(smsConfigInfo.getPlatform());

            //保存smsRecord
            SmsRecordInfo smsRecord = saveSmsRecord(smsParamDTO, smsTemplate, smsConfigInfo, channelBaseInfo);
            if (smsRecord == null) {
                log.error("【发送短信】保存短信发送记录错误");
                return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "系统繁忙，数据保存异常");
            }

            //发送短信验证码
            SmsResultDTO smsResult = SmsSendFactory.getService(smsConfigInfo.getPlatform()).sendSms(smsParamDTO, smsTemplate, smsConfigInfo);
            this.updateSmsRecord(smsRecord, smsResult);

            if (smsResult.isSuccess()) {
                return new ResponseVo(AppRspCodeConstant.SUCCESS, "短信验证码发送成功，请注意查收");
            }
        }catch (Exception exception){
            exception.printStackTrace();
            String message = StrUtil.format("【smsParamDTO】{},【appCode】{},【channelCode】{}", JSON.toJSONString(smsParamDTO), applicationInfo.getAppCode(), channelBaseInfo.getChannelCode());
            notifyExceptionService.notifyNoticeInfo("SMS_SEND_EXC", "短信发送异常",message, exception);
        }
        return new ResponseVo(AppRspCodeConstant.SYS_EXCEPTION, "短信发送失败！请稍后重试" );
    }

    @Async
    @Override
    public void updateSmsRecord(SmsRecordInfo smsRecord, SmsResultDTO smsResult){
        smsRecord.setCode(smsResult.getCode());
        smsRecord.setMessage(smsResult.getMessage());
        smsRecord.setOutOrderNo(smsResult.getOutOrderNo());
        smsRecord.setResult(smsResult.getResult());

        if (AppRspCodeConstant.SUCCESS.equals(smsResult.getCode())) {
            smsRecord.setStatus(1);
        }else{
            smsRecord.setStatus(-1);
        }
        boolean updateFlag = updateById(smsRecord);
        log.info("【sms更新smsRecord结果：】{}【sms更新smsRecord结果：】{}", updateFlag, smsResult.getCode() + "：" + smsResult.getMessage());
    }

    /**
     * 保存并返回id
     * @return
     */
    private SmsRecordInfo saveSmsRecord(SmsParamDTO smsParamDTO, SmsTemplateInfo smsTemplate, SmsConfigInfo smsConfigInfo, ChannelBaseInfo channelBaseInfo) {
        SmsRecordInfo smsRecord = new SmsRecordInfo();
        smsRecord.setPlatform(smsParamDTO.getPlatform());
        smsRecord.setMobile(smsParamDTO.getMobie());
        smsRecord.setOtype(smsParamDTO.getOtype());
        smsRecord.setParamInfo(JSON.toJSONString(smsParamDTO.getParamArray()));
        smsRecord.setReqIp(smsParamDTO.getReqIp());
        smsRecord.setOrderNo(smsParamDTO.getOrderNo());
        smsRecord.setConfigId(smsConfigInfo.getId());

        smsRecord.setChannelName(channelBaseInfo.getChannelName());
        smsRecord.setChannelCode(channelBaseInfo.getChannelCode());

        smsRecord.setTemplateContent(smsTemplate.getTemplateContent());
        smsRecord.setStatus(0);

        boolean saveFlag = this.save(smsRecord);
        if (saveFlag) {
            return smsRecord;
        } else {
            return null;
        }
    }

    @Override
    public void querySmsRecordResult(){

        // 查询待查询的短信记录
        List<SmsRecordInfo> recordInfoList = this.baseMapper.selectWaitQueryRecord();

        for (SmsRecordInfo smsRecordInfo : recordInfoList) {
            String platform = smsRecordInfo.getPlatform();

            QueryParamDTO queryParamDTO = new QueryParamDTO();

            SmsConfigInfo smsConfigInfo = smsConfigInfoService.getById(smsRecordInfo.getConfigId());

            SmsSendFactory.getService(platform).querySendResult(queryParamDTO, smsConfigInfo);
        }
    }


}
